package com.huiying.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huiying.entity.entity.Message;
import com.huiying.entity.entity.User;
import com.huiying.mapper.MessageMapper;
import com.huiying.mapper.UserMapper;
import com.huiying.service.MessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 消息服务实现类
 */
@Service
@Slf4j
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
     * 根据会话ID获取聊天历史消息
     *
     * @param conversationId 会话ID
     * @param page           页码 (从0开始)
     * @param size           每页数量
     * @return 消息列表，按时间倒序排列，并填充发送者用户信息
     */
    @Override
    public List<Message> getConversationHistory(Long conversationId, int page, int size) {
        Page<Message> messagePage = new Page<>(page + 1, size);

        QueryWrapper<Message> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("conversation_id", conversationId)
                .orderByDesc("created_time");

        IPage<Message> resultPage = baseMapper.selectPage(messagePage, queryWrapper);
        List<Message> messages = resultPage.getRecords();
        log.info("会话ID {}，信息列表{}",conversationId,messages);

        if (messages.isEmpty()) {
            log.info("查询会话ID {} 的历史消息：页码 {}, 每页数量 {}, 实际返回 0 条。",
                    conversationId, page, size);
            return messages;
        }

        // --- 开始填充 senderUsername 和 senderAvatar ---

        // 1. 收集所有唯一的发送者ID
        Set<Long> senderIds = new HashSet<>();
        messages.forEach(msg -> senderIds.add(msg.getSenderId()));

        // 2. 批量查询这些发送者的用户信息
        // 假设 UserService 有一个方法可以根据多个ID批量查询用户
        // 例如：userService.listByIds(senderIds) 或自定义方法
        List<User> senders = userMapper.selectBatchIds(new ArrayList<>(senderIds)); // 假设您的 UserService 有此方法
        // 或者直接调用 MyBatis-Plus 的 baseMapper.selectBatchIds(senderIds) 如果 UserService 没有封装
        // List<User> senders = userMapper.selectBatchIds(new ArrayList<>(senderIds)); // 如果直接注入 UserMapper

        // 将用户列表转换为 Map，方便通过 ID 查找
        Map<Long, User> senderMap = senders.stream()
                .collect(Collectors.toMap(User::getId, user -> user));

        // 3. 遍历消息列表，填充发送者的昵称和头像
        messages.forEach(msg -> {
            User sender = senderMap.get(msg.getSenderId());
            if (sender != null) {
                msg.setSenderUsername(sender.getUsername());
                msg.setSenderAvatar(sender.getAvatar());
            } else {
                // 如果找不到发送者信息（例如用户已被删除），可以给一个默认值或记录警告
                log.warn("无法找到发送者ID为 {} 的用户信息，消息ID: {}", msg.getSenderId(), msg.getId());
                msg.setSenderUsername("未知用户");
                // msg.setSenderAvatar("默认头像URL"); // 可以设置一个默认头像
            }
        });

        // --- 填充结束 ---

        log.info("查询会话ID {} 的历史消息：页码 {}, 每页数量 {}, 实际返回 {} 条，并填充了发送者信息。",
                conversationId, page, size, messages.size());
        return messages;
    }

    /**
     * 标记指定消息为已读状态
     *
     * @param messageId 消息ID
     * @param readerId  读取消息的用户ID (接收者ID)
     * @return 是否成功标记为已读
     */
    @Override
    @Transactional
    public boolean markMessageAsRead(Long messageId, Long readerId) {
        Message message = baseMapper.selectById(messageId);

        if (message == null) {
            log.warn("尝试标记不存在的消息ID {} 为已读。", messageId);
            return false;
        }

        if (message.getReceiverId().equals(readerId) && message.getStatus() != Message.MessageStatus.READ) {
            message.setStatus(Message.MessageStatus.READ);
            // message.setReadTime(LocalDateTime.now()); // 如果 Message 实体有 readTime 字段，可以取消注释
            int rowsAffected = baseMapper.updateById(message);
            if (rowsAffected > 0) {
                log.info("消息ID {} 已被用户 {} 标记为已读。", messageId, readerId);
                // TODO: 可以在这里通知发送者此消息已被读取，如果需要实时“已读”回执功能
                // 由于 ChatController 中的 sendMessage 方法已经发送了消息给接收者，
                // 如果需要已读回执，可以在这里再发一个消息给 senderId
                /*
                try {
                    // 假设您有一个专门用于发送消息状态更新的DTO
                    MessageStatusUpdateDTO statusUpdate = new MessageStatusUpdateDTO(
                        message.getId(), Message.MessageStatus.READ, readerId, message.getConversationId());
                    messagingTemplate.convertAndSendToUser(
                        message.getSenderId().toString(),
                        "/queue/message-status-updates", // 发送给发送者的队列
                        statusUpdate
                    );
                    log.debug("已读回执消息发送给发送者 {}，消息ID: {}", message.getSenderId(), message.getId());
                } catch (Exception e) {
                    log.error("发送消息 {} 已读回执失败: {}", message.getId(), e.getMessage());
                }
                */
                return true;
            }
        } else {
            log.info("消息ID {} 不符合已读条件（接收者不符或已是已读状态）。", messageId);
        }
        return false;
    }

    /**
     * 获取指定用户的离线消息（状态为 SENT 或 DELIVERED 且接收者为该用户）
     *
     * @param userId 接收离线消息的用户ID
     * @return 离线消息列表，并填充发送者用户信息
     */
    @Override
    public List<Message> getOfflineMessages(Long userId) {
        QueryWrapper<Message> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("receiver_id", userId)
                .eq("receiver_deleted", false)
                .in("status", Message.MessageStatus.SENT.name(), Message.MessageStatus.DELIVERED.name())
                .orderByAsc("created_time");

        List<Message> offlineMessages = baseMapper.selectList(queryWrapper);

        if (offlineMessages.isEmpty()) {
            log.info("查询到用户 {} 的 0 条离线消息。", userId);
            return offlineMessages;
        }

        // --- 填充 senderUsername 和 senderAvatar 的逻辑与 getConversationHistory 类似 ---
        Set<Long> senderIds = new HashSet<>();
        offlineMessages.forEach(msg -> senderIds.add(msg.getSenderId()));

        List<User> senders = userMapper.selectBatchIds(new ArrayList<>(senderIds));
        Map<Long, User> senderMap = senders.stream()
                .collect(Collectors.toMap(User::getId, user -> user));

        offlineMessages.forEach(msg -> {
            User sender = senderMap.get(msg.getSenderId());
            if (sender != null) {
                msg.setSenderUsername(sender.getUsername());
                msg.setSenderAvatar(sender.getAvatar());
            } else {
                log.warn("无法找到离线消息发送者ID为 {} 的用户信息，消息ID: {}", msg.getSenderId(), msg.getId());
                msg.setSenderUsername("未知用户");
            }
        });
        // --- 填充结束 ---

        log.info("查询到用户 {} 的 {} 条离线消息，并填充了发送者信息。", userId, offlineMessages.size());
        return offlineMessages;
    }

    /**
     * 更新消息的状态
     *
     * @param messageId 消息ID
     * @param newStatus 新的消息状态
     * @return 是否成功更新状态
     */
    @Override
    @Transactional
    public boolean updateMessageStatus(Long messageId, Message.MessageStatus newStatus) {
        Message message = baseMapper.selectById(messageId);
        if (message == null) {
            log.warn("尝试更新不存在的消息ID {} 的状态。", messageId);
            return false;
        }
        if (message.getStatus() == newStatus) {
            log.info("消息ID {} 的状态已经是 {}，无需更新。", messageId, newStatus);
            return true;
        }
        message.setStatus(newStatus);
        int rowsAffected = baseMapper.updateById(message);
        if (rowsAffected > 0) {
            log.info("消息ID {} 的状态已更新为 {}.", messageId, newStatus);
            return true;
        }
        return false;
    }

    /**
     * 用户上线时，推送其离线消息，并更新消息状态为 DELIVERED
     *
     * @param userId 上线用户的ID
     */
    @Override
    @Transactional
    public void pushOfflineMessages(Long userId) {
        // pushOfflineMessages 会调用 getOfflineMessages，而 getOfflineMessages 已经填充了用户信息
        List<Message> offlineMessages = getOfflineMessages(userId);
        if (offlineMessages.isEmpty()) {
            log.info("用户 {} 没有离线消息需要推送。", userId);
            return;
        }

        log.info("开始向用户 {} 推送 {} 条离线消息...", userId, offlineMessages.size());
        for (Message message : offlineMessages) {
            try {
                messagingTemplate.convertAndSendToUser(
                        userId.toString(),
                        "/queue/messages",
                        message
                );
                message.setStatus(Message.MessageStatus.DELIVERED);
                baseMapper.updateById(message);
                log.debug("离线消息 ID: {} 已推送并更新状态为 DELIVERED。", message.getId());
            } catch (Exception e) {
                log.error("推送离线消息 ID: {} 给用户 {} 失败: {}", message.getId(), userId, e.getMessage(), e);
            }
        }
        log.info("用户 {} 的离线消息推送完成。", userId);
    }

    /**
     * 保存消息内容到数据库
     *
     * @param message 待保存的消息对象
     */
    @Override
    @Transactional
    public void saveMessage(Message message) {
        if (message == null) {
            log.warn("尝试保存空消息对象。");
            return;
        }
        if (message.getContent() == null || message.getContent().trim().isEmpty()) {
            log.warn("消息内容为空或只包含空格，不予保存。");
            return;
        }
        boolean saved = super.save(message);
        if (saved) {
            log.info("消息保存成功。消息ID: {}", message.getId());
        } else {
            log.error("消息保存失败，消息对象: {}", message);
        }
    }
}